package com.skp.shaphan.actions;

import java.io.StringReader;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParser;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.parser.CCJSqlParserTokenManager;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitor;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.drop.Drop;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.replace.Replace;
import net.sf.jsqlparser.statement.select.FromItemVisitor;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectVisitor;
import net.sf.jsqlparser.statement.select.SubJoin;
import net.sf.jsqlparser.statement.select.SubSelect;
import net.sf.jsqlparser.statement.select.Union;
import net.sf.jsqlparser.statement.truncate.Truncate;
import net.sf.jsqlparser.statement.update.Update;

import com.skp.job.ProjectJobException;
import com.skp.shaphan.model.ConnectionDetails;
import com.skp.shaphan.sql.SQLPreProcessor;
import com.skp.shaphan.ui.SQLEditor;
import com.skp.shaphan.ui.windows.ParseSqlWindow;
import com.sun.org.apache.xpath.internal.axes.WalkingIterator;

/**
 * Runs a piece of SQL from a SQLEditor
 * @author Stephen Phillips
 *
 */
public class ParseSQLAction extends Thread implements Runnable, StatementVisitor, SelectVisitor, FromItemVisitor {
	private SQLEditor editor;
	private ParseSqlWindow window;
	
	public ParseSQLAction() {
		
	}
	
	@Override
	public void run() {
		window = new ParseSqlWindow();
		window.setVisible(true);

		// What SQL do we run
		ConnectionDetails cd = editor.getConnection();
		String sqlStatement = editor.getSQL();
		System.out.println("sql = " + sqlStatement);
		//SQLPreProcessor spp = cd.getSQLPreprocessor(sqlStatement);
		//sqlStatement = spp.process();
		System.out.println("now sql = " + sqlStatement);
		
		window.setSQL(sqlStatement);
		
		CCJSqlParserManager man = new CCJSqlParserManager();
		Statement parsed;
		try {
			parsed = man.parse(new StringReader(sqlStatement));
			parsed.accept(this);
		} catch (JSQLParserException e) {
			ProjectJobException.displayException(e);
		}
		
	}

	public SQLEditor getEditor() {
		return editor;
	}

	public void setEditor(SQLEditor editor) {
		this.editor = editor;
	}

	@Override
	public void visit(Select select) {
		window.setSQLType("Select");
		select.getSelectBody().accept(this);
	}

	@Override
	public void visit(Delete delete) {
		window.setSQLType("Delete");
	}

	@Override
	public void visit(Update update) {
		window.setSQLType("Update");
	}

	@Override
	public void visit(Insert insert) {
		window.setSQLType("Insert");
	}

	@Override
	public void visit(Replace replace) {
		window.setSQLType("Replace");
	}

	@Override
	public void visit(Drop drop) {
		window.setSQLType("Drop");
	}

	@Override
	public void visit(Truncate truncate) {
		window.setSQLType("Truncate");
	}

	@Override
	public void visit(CreateTable createTable) {
		window.setSQLType("Create Table");
	}

	@Override
	public void visit(PlainSelect plainSelect) {
		System.out.println("plainSelect");
		plainSelect.getFromItem().accept(this);
	}

	@Override
	public void visit(Union union) {
		window.setError("This statement has a Union, and we haven't added parsing for a Union");
	}

	@Override
	public void visit(Table tableName) {
		System.out.println("table: " + tableName.getWholeTableName());
		window.addTable(tableName);
	}

	@Override
	public void visit(SubSelect subSelect) {
		window.setError("This statement has a SubSelect, and we haven't added parsing for a SubSelect");
	}

	@Override
	public void visit(SubJoin subjoin) {
		window.setError("This statement has a SubJoin, and we haven't added parsing for a SubJoin");
	}
}
